//
//  UIView+MHFrame.m
//  MHDevLibExample
//
//  Created by apple on 16/5/12.
//  Copyright © 2016年 Mike_He. All rights reserved.
//

#import "UIView+MHFrame.h"
#import <objc/runtime.h>

@implementation UIView (MHFrame)

- (void)setMh_x:(CGFloat)mh_x
{
    CGRect frame = self.frame;
    frame.origin.x = mh_x;
    self.frame = frame;
}
- (CGFloat)mh_x
{
    return self.frame.origin.x;
}




- (void)setMh_y:(CGFloat)mh_y
{
    CGRect frame = self.frame;
    frame.origin.y = mh_y;
    self.frame = frame;
}
- (CGFloat)mh_y
{
    return self.frame.origin.y;
}




- (void)setMh_centerX:(CGFloat)mh_centerX
{
    CGPoint center = self.center;
    center.x = mh_centerX;
    self.center = center;
}
- (CGFloat)mh_centerX
{
    return self.center.x;
}



- (void)setMh_centerY:(CGFloat)mh_centerY
{
    CGPoint center = self.center;
    center.y = mh_centerY;
    self.center = center;
}
- (CGFloat)mh_centerY
{
    return self.center.y;
}




- (void)setMh_width:(CGFloat)mh_width
{
    CGRect frame = self.frame;
    frame.size.width = mh_width;
    self.frame = frame;
}
- (CGFloat)mh_width
{
    return self.frame.size.width;
}





- (void)setMh_height:(CGFloat)mh_height
{
    CGRect frame = self.frame;
    frame.size.height = mh_height;
    self.frame = frame;
}
- (CGFloat)mh_height
{
    return self.frame.size.height;
}





- (void)setMh_size:(CGSize)mh_size
{
    CGRect frame = self.frame;
    frame.size = mh_size;
    self.frame = frame;
}
- (CGSize)mh_size
{
    return self.frame.size;
}





- (void)setMh_origin:(CGPoint)mh_origin
{
    CGRect frame = self.frame;
    frame.origin = mh_origin;
    self.frame = frame;
}
- (CGPoint)mh_origin
{
    return self.frame.origin;
}


- (void)setMh_top:(CGFloat)mh_top
{
    CGRect frame = self.frame;
    frame.origin.y = mh_top;
    self.frame = frame;
}
- (CGFloat)mh_top
{
    return self.frame.origin.y;
}


- (void)setMh_left:(CGFloat)mh_left
{
    CGRect frame = self.frame;
    frame.origin.x = mh_left;
    self.frame = frame;
}
- (CGFloat)mh_left
{
    return self.frame.origin.x;
}


- (void)setMh_bottom:(CGFloat)mh_bottom
{
    CGRect frame = self.frame;
    frame.origin.y = mh_bottom - frame.size.height;
    self.frame = frame;
}
- (CGFloat)mh_bottom{
    return self.frame.origin.y + self.frame.size.height;
}


- (void)setMh_right:(CGFloat)mh_right
{
    CGRect frame = self.frame;
    frame.origin.x = mh_right - frame.size.width;
    self.frame = frame;
}
- (CGFloat)mh_right{
    return self.frame.origin.x + self.frame.size.width;
}



#pragma mark - frame
- (void)setMm_x:(CGFloat)mdh_x {
    CGRect frame = self.frame;
    frame.origin.x = mdh_x;
    self.frame = frame;
}

- (CGFloat)mdh_x {
    return self.frame.origin.x;
}

- (void)setMm_y:(CGFloat)mdh_y {
    CGRect frame = self.frame;
    frame.origin.y = mdh_y;
    self.frame = frame;
}
- (CGFloat)mdh_y {
    return self.frame.origin.y;
}
- (void)setMm_w:(CGFloat)mdh_w {
    CGRect frame = self.frame;
    frame.size.width = mdh_w;
    self.frame = frame;
}

- (CGFloat)mdh_w {
    return self.frame.size.width;
}

- (void)setMm_h:(CGFloat)mdh_h {
    CGRect frame = self.frame;
    frame.size.height = mdh_h;
    self.frame = frame;
}

- (CGFloat)mdh_h {
    return self.frame.size.height;
}

-(CGFloat)mdh_centerX {
    return self.center.x;
}

-(CGFloat)mdh_centerY {
    return self.center.y;
}

-(void)setMm_centerX:(CGFloat)mdh_centerX {
    CGPoint center = self.center;
    center.x = mdh_centerX;
    self.center = center;
}

-(void)setMm_centerY:(CGFloat)mdh_centerY {
    CGPoint center = self.center;
    center.y = mdh_centerY;
    self.center = center;
}

- (CGFloat)mdh_r {
    NSCAssert(self.superview, @"must add subview first");
    return self.superview.mdh_w - self.mdh_maxX;
}

- (void)setMm_r:(CGFloat)mdh_r {
    self.mdh_x += self.mdh_r - mdh_r;
}

- (CGFloat)mdh_b {
    NSCAssert(self.superview, @"must add subview first");
    return self.superview.mdh_h - self.mdh_maxY;
}

- (void)setMm_b:(CGFloat)mdh_b {
    self.mdh_y += self.mdh_b - mdh_b;
}

- (CGFloat)mdh_maxY {
    return CGRectGetMaxY(self.frame);
}
- (CGFloat)mdh_minY {
    return CGRectGetMinY(self.frame);
}
- (CGFloat)mdh_maxX {
    return CGRectGetMaxX(self.frame);
}
- (CGFloat)mdh_minX {
    return CGRectGetMinX(self.frame);
}

#pragma mark - chain call

-(UIView *(^)(CGFloat))mdh_top {
    @weakify(self);
    return ^(CGFloat m_top){
        @strongify(self);
        self.mdh_y = m_top;
        return self;
    };
}

-(UIView *(^)(CGFloat))mdh_bottom {
    @weakify(self);
    return ^(CGFloat m_bottom){
        @strongify(self);
        self.mdh_b = m_bottom;
        return self;
    };
}
-(UIView *(^)(CGFloat))mdh_flexToBottom {
    @weakify(self);
    return ^(CGFloat m_flexToBottom){
        @strongify(self);
        self.mdh_h += self.mdh_b - m_flexToBottom;
        return self;
    };
}
-(UIView *(^)(CGFloat))mdh_left {
    @weakify(self);
    return ^(CGFloat m_left){
        @strongify(self);
        self.mdh_x = m_left;
        return self;
    };
}

-(UIView *(^)(CGFloat))mdh_right {
    @weakify(self);
    return ^(CGFloat m_right){
        @strongify(self);
        self.mdh_r = m_right;
        return self;
    };
}
-(UIView *(^)(CGFloat))mdh_flexToRight {
    @weakify(self);
    return ^(CGFloat m_flexToRight){
        @strongify(self);
        self.mdh_w += self.mdh_r - m_flexToRight;
        return self;
    };
}

-(UIView *(^)(CGFloat))mdh_width {
    @weakify(self);
    return ^(CGFloat m_width){
        @strongify(self);
        self.mdh_w = m_width;
        return self;
    };
}
-(UIView *(^)(CGFloat))mdh_height {
    @weakify(self);
    return ^(CGFloat m_height){
        @strongify(self);
        self.mdh_h = m_height;
        return self;
    };
}

- (UIView *(^)(CGFloat))mdh__centerX {
    @weakify(self);
    return ^(CGFloat x){
        @strongify(self);
        NSAssert(self.mdh_w, @"must set width first");
        self.mdh_centerX = x;
        return self;
    };
}

- (UIView *(^)(CGFloat))mdh__centerY {
    @weakify(self);
    return ^(CGFloat y){
        @strongify(self);
        NSAssert(self.mdh_h, @"must set height first");
        self.mdh_centerY = y;
        return self;
    };
}


-(UIView *(^)(void))mdh_center {
    @weakify(self);
    return ^{
        @strongify(self);
        if (self.superview) {
            self.mdh_centerX = self.superview.mdh_w / 2;
            self.mdh_centerY = self.superview.mdh_h / 2;
        }
        return self;
    };
}

-(UIView *(^)(void))mdh_fill {
    @weakify(self);
    return ^{
        @strongify(self);
        if (self.superview) {
            self.mdh_x = self.mdh_y = 0;
            self.mdh_w = self.superview.mdh_w;
            self.mdh_h = self.superview.mdh_h;
        }
        return self;
    };
}

-(UIView *(^)(void))mdh_sizeToFit {
    @weakify(self);
    return ^{
        @strongify(self);
        [self sizeToFit];
        return self;
    };
}
-(UIView *(^)(CGFloat w, CGFloat h))mdh_sizeToFitThan {
    @weakify(self);
    return ^(CGFloat w, CGFloat h){
        @strongify(self);
        [self sizeToFit];
        if (self.mdh_w < w)
            self.mdh_w = w;
        if (self.mdh_h < h)
            self.mdh_h = h;
        return self;
    };
}

- (UIView * (^)(CGFloat space))mdh_hstack {
    @weakify(self);
    return ^(CGFloat space) {
        @strongify(self);
        if (self.mdh_sibling) {
            self.mdh__centerY(self.mdh_sibling.mdh_centerY).mdh_left(self.mdh_sibling.mdh_maxX+space);
        }
        return self;
    };
}

- (UIView * (^)(CGFloat space))mdh_vstack {
    @weakify(self);
    return ^(CGFloat space) {
        @strongify(self);
        if (self.mdh_sibling) {
            self.mdh__centerX(self.mdh_sibling.mdh_centerX).mdh_top(self.mdh_sibling.mdh_maxY+space);
        }
        return self;
    };
}

- (UIView *)mdh_sibling {
    NSUInteger idx = [self.superview.subviews indexOfObject:self];
    if (idx == 0 || idx == NSNotFound)
        return nil;
    return self.superview.subviews[idx-1];
}

- (UIViewController *)mdh_viewController {
    UIView *view = self;
    while (view) {
        UIResponder *nextResponder = [view nextResponder];
        if ([nextResponder isKindOfClass:[UIViewController class]]) {
            return (UIViewController *)nextResponder;
        }
        view = view.superview;
      }
    return nil;
}



static void *kUIViewLayoutMethodPropertyBottomGap = &kUIViewLayoutMethodPropertyBottomGap;
static void *kUIViewLayoutMethodPropertyTopGap = &kUIViewLayoutMethodPropertyTopGap;
static void *kUIViewLayoutMethodPropertyLeftGap = &kUIViewLayoutMethodPropertyLeftGap;
static void *kUIViewLayoutMethodPropertyRightGap = &kUIViewLayoutMethodPropertyRightGap;

- (CGFloat)mdh_safeAreaBottomGap
{
    NSNumber *gap = objc_getAssociatedObject(self, kUIViewLayoutMethodPropertyBottomGap);
    if (gap == nil) {
        if (@available(iOS 11, *)) {
            if (self.superview.safeAreaLayoutGuide.layoutFrame.size.height > 0) {
                gap = @((self.superview.mdh_h - self.superview.safeAreaLayoutGuide.layoutFrame.origin.y - self.superview.safeAreaLayoutGuide.layoutFrame.size.height));
            } else {
                gap = nil;
            }
        } else {
            gap = @(0);
        }
        objc_setAssociatedObject(self, kUIViewLayoutMethodPropertyBottomGap, gap, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return gap.floatValue;
}

- (CGFloat)mdh_safeAreaTopGap
{
    NSNumber *gap = objc_getAssociatedObject(self, kUIViewLayoutMethodPropertyTopGap);
    if (gap == nil) {
        if (@available(iOS 11, *)) {
            gap = @(self.superview.safeAreaLayoutGuide.layoutFrame.origin.y);
        } else {
            gap = @(0);
        }
        objc_setAssociatedObject(self, kUIViewLayoutMethodPropertyTopGap, gap, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return gap.floatValue;
}

- (CGFloat)mdh_safeAreaLeftGap
{
    NSNumber *gap = objc_getAssociatedObject(self, kUIViewLayoutMethodPropertyLeftGap);
    if (gap == nil) {
        if (@available(iOS 11, *)) {
            gap = @(self.superview.safeAreaLayoutGuide.layoutFrame.origin.x);
        } else {
            gap = @(0);
        }
        objc_setAssociatedObject(self, kUIViewLayoutMethodPropertyLeftGap, gap, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return gap.floatValue;
}

- (CGFloat)mdh_safeAreaRightGap
{
    NSNumber *gap = objc_getAssociatedObject(self, kUIViewLayoutMethodPropertyRightGap);
    if (gap == nil) {
        if (@available(iOS 11, *)) {
            gap = @((self.superview.mdh_w - self.superview.safeAreaLayoutGuide.layoutFrame.origin.x - self.superview.safeAreaLayoutGuide.layoutFrame.size.width));
        } else {
            gap = @(0);
        }
        objc_setAssociatedObject(self, kUIViewLayoutMethodPropertyRightGap, gap, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return gap.floatValue;
}


@end
